﻿using AutoMapper;
using MediatR;
using SmartCity.ProcessEngine.Api.Write.Application.Command.EventHandling;
using SmartCity.ProcessEngine.Domain.Entities;
using SmartCity.ProcessEngine.ErrorCode;
using SmartCity.ProcessEngine.Infrastructure.Interface;
using System.Transactions;
using Yitter.IdGenerator;

namespace SmartCity.ProcessEngine.Api.Write.Application.CommandHandler.EventHandling
{
    public class CreateInstanceHandler : IRequestHandler<CreateInstanceCommand, ApiResult<int>>
    {
        private readonly IBaseRepository<InstanceModel> instanceRepo;
        private readonly IBaseRepository<FormModel> formRepo;
        private readonly IBaseRepository<FormNodeConfigModel> nodeCfgRepo;
        private readonly IBaseRepository<NodeModel> nodeRepo;
        private readonly IBaseRepository<InstanceRecardModel> recardRepo;
        private readonly IMapper mapper;
        private readonly ILogger<CreateInstanceHandler> logger;

        /// <summary>
        /// 在构造函数中,注入所需要的资源
        /// </summary>
        /// <param name="instanceRepo">实例仓储</param>
        /// <param name="formRepo">流程表单仓储</param>
        /// <param name="nodeCfgRepo">节点配置仓储</param>
        /// <param name="nodeRepo">节点仓储</param>
        /// <param name="recardRepo">实例审批记录仓储</param>
        /// <param name="mapper">映射组件对象</param>
        public CreateInstanceHandler(IBaseRepository<InstanceModel> instanceRepo, IBaseRepository<FormModel> formRepo, IBaseRepository<FormNodeConfigModel> nodeCfgRepo, IBaseRepository<NodeModel> nodeRepo,IBaseRepository<InstanceRecardModel> recardRepo,IMapper mapper,ILogger<CreateInstanceHandler> logger)
        {
            this.instanceRepo = instanceRepo;
            this.formRepo = formRepo;
            this.nodeCfgRepo = nodeCfgRepo;
            this.nodeRepo = nodeRepo;
            this.recardRepo = recardRepo;
            this.mapper = mapper;
            this.logger = logger;
        }

        /// <summary>
        /// 保存实例的处理方法
        /// </summary>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<ApiResult<int>> Handle(CreateInstanceCommand request, CancellationToken cancellationToken)
        {
            var form =await  formRepo.GetModel(request.FormId);
            if (form == null) {
                return new ApiResult<int>().Error("你要新增的流程不存在!");
            }

            //查到当前流程的配置节点
            var currentCfgNode = nodeCfgRepo.GetAll().Where(x => x.FormId == request.FormId&&x.IsDeleted==false).OrderBy(x => x.Id).FirstOrDefault();
            //流程的节点
            var currentNode =await nodeRepo.GetModel(currentCfgNode.CurrentNodeId);

            //查到当前流程的下一个配置节点
            var nextCfgNode = nodeCfgRepo.GetAll().Where(x => x.FormId == request.FormId&&x.Id != currentCfgNode.Id && x.IsDeleted == false).OrderBy(x => x.Id).FirstOrDefault();
            var nextNode = await nodeRepo.GetModel(nextCfgNode.CurrentNodeId);


            //先构建实例实体
            InstanceModel instance = mapper.Map<InstanceModel>(request);  //把请求命令转为 流程实例 实体
            instance.Id = YitIdHelper.NextId();
            instance.FlowStatus = InstanceStatus.申请;//新的流程实例,状态一定是 申请
            instance.CurrentNodeId = currentCfgNode.Id;// currentNode.Id;//???从节点配置中查
            instance.CurrentNodeName = currentNode.NodeName;
            instance.CurrentOperatorName = currentCfgNode.AccountName;

            //下一个节点的信息
            instance.NextNodeId = nextCfgNode.Id;
            instance.NextNodeName = nextNode?.NodeName;
            instance.NextOperatorName = nextCfgNode?.AccountName;
            instance.UpdateTime = DateTime.Now;


            var r = 0;
            var r1 = 0;

            //构建实例的审批记录实体
            InstanceRecardModel instanceRecardModel = new InstanceRecardModel();
            instanceRecardModel.Id = YitIdHelper.NextId();
            instanceRecardModel.IntanceId = instance.Id;
            instanceRecardModel.NodeId = instance.CurrentNodeId;
            instanceRecardModel.NodeName = instance.CurrentNodeName;
            instanceRecardModel.OperatorName = instance.CurrentOperatorName;
            instanceRecardModel.OperatorOpinion = $"{request.StarterName}新发起{form.FormName}流程";
            instanceRecardModel.ApproveStatus = ApproveStatus.已提交;


            using (TransactionScope tran = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled) )
            {
                try
                {

                    r = await instanceRepo.CreateAsync(instance);
                    r1 = await recardRepo.CreateAsync(instanceRecardModel);
                    tran.Complete();
                }
                catch (Exception e)
                {
                    logger.LogError("新建流程实例时发生异常:"+e.Message);
                    throw e;
                }
            }

           
            if (r1 > 0&&r>0)
            {
                return new ApiResult<int>().AddSuccess("流程实例", r);
            }
            else
            {
                return new ApiResult<int>().AddFail("流程实例");
            }


        }
    }
}
